#include "typedef.h"

typedef struct SysBuffer
{
    char *buff;
    int  size;
    int ptr;
    runable full_handle;
    runable empty_handle;
} *SysBuffer;

static void do_full_handle(SysBuffer sbf)
{
    if (sbf->full_handle)
    {
        int handle_cnt = 0;
        handle_cnt = sbf->full_handle(sbf);
        sbf->ptr -= handle_cnt;
    }
    else
    {
        sbf->ptr = 0;
    }
}

static boolean do_empty_handle(SysBuffer sbf)
{
    int read_cnt = 0;
    if(sbf->empty_handle)
    {
        read_cnt = sbf->empty_handle(sbf);
    }
    if(0 == read_cnt)
    {
        return False;
    }
    else
    {
        sbf->ptr += read_cnt;
    }
    return True;
}

boolean putc_buffer(SysBuffer sbf, char c)
{
    if(!sbf)
    {
        return False;
    }
    if(sbf->ptr >= sbf->size)
    {
        return False;
    }
    *(sbf->buff + sbf->ptr) = c;
    sbf->ptr++;
    *(sbf->buff + sbf->ptr) = '\0';
    if((c == '\n') || (sbf->ptr >= sbf->size))
    {
        do_full_handle(sbf);
    }
    return True;
}

void flush_buffer(SysBuffer sbf)
{
    if (sbf->ptr > 0)
    {
        do_full_handle(sbf);
    }
}

char getc_buffer(SysBuffer sbf)
{
    char c='\0';
    if(!sbf)
    {
        return '\0';
    }
    if(sbf->ptr == 0)
    {
        if(!do_empty_handle(sbf))
        {
            return '\0';
        }
    }
    c = *(sbf->buff + sbf->ptr -1);
    sbf->ptr--;
    return c;
}

int write_buffer(SysBuffer sbf, const char *buff, int size, int *actual)
{
    boolean status;
    int real_cnt = 0;
    for (int i = 0; *buff && (i < size); i++, buff++)
    {
        status = putc_buffer(sbf, *buff);
        if(status)
        {
            real_cnt++;
        }
        else
        {
            break;
        }
    }
    if(actual)
    {
        *actual = real_cnt;
    }
    return real_cnt;
}